package com.sd.repay.service.impl;

import com.sd.repay.common.CommonResult;
import com.sd.repay.common.Constants;
import com.sd.repay.pojo.*;
import com.sd.repay.service.*;
import com.sd.repay.transfer.Transfer;
import com.sd.repay.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * @author sd
 * @Description: 还款Service接口实现类
 * @date 2017年10月25日
 */
@Service
public class RepayServiceImpl implements RepayService {

    private static Logger log = LoggerFactory.getLogger(RepayServiceImpl.class);

    @Autowired
    private MerTokenService tokenService;
    @Autowired
    private AroundPayOrderService aroundPayOrderService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private MerchantService merchantService;
    @Autowired
    private RepayPlanDetailService planDetailService;
    @Autowired
    private RepayPlanService planService;
    @Autowired
    private CardManageService cardManageService;
    @Autowired
    private ZqMerchantService zqMerchantService;
    @Autowired
    private MerFeeService merFeeService;
    @Autowired
    private WithdrawOrderService withdrawOrderService;

    /**
     * channel：通道编号
     * cardNo：卡片编号
     * amount：出账金额
     * planNo：计划编号
     * merchantNo：商户号
     *
     * @param params
     */
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public CommonResult executeRepay(Map<String, String> params) {

        log.info("执行代付还款明细参数-------->" + JsonUtil.objectToJson(params));

        String acqCode = params.get("acqCode");
        String cardNo = params.get("cardNo");
        String amountStr = params.get("amount");
        String planNo = params.get("planNo");
        String merchantNo = params.get("merchantNo");

        //sql影响的行数
        int count;
        TransferOrder resTransfer = new TransferOrder();

        if (StringUtil.isEmpty(acqCode, cardNo, amountStr, planNo, merchantNo)) {
            log.info("执行代付还款明细编号[{}]错误信息：参数不能有空", planNo);
            resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
            resTransfer.setResultMsg("参数不能有空");
            return CommonResult.ok(resTransfer);
        }

        try {
            BigDecimal amount = new BigDecimal(amountStr);
            //根据商户号获取商户信息
            Map<String, Object> merInfo = merchantService.getMerInfoByMerNo(merchantNo);
            log.info("代付还款明细编号[{}]所属商户号[{}]对应商户信息[{}]", new Object[]{planNo, merchantNo, JsonUtil.objectToJson(merInfo)});
            if (merInfo == null || merInfo.isEmpty()) {
                resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                resTransfer.setResultMsg("商户信息不存在");
                return CommonResult.ok(resTransfer);
            }
            String oemType = StringUtil.filterNull(merInfo.get("oem_type"));
            //根据卡片编号获取卡片对象
            Map<String, Object> cardInfo = cardManageService.getCardManageByCardNo(cardNo);
            log.info("代付还款明细编号[{}]所属卡片编号号[{}]对应卡片信息[{}]", new Object[]{planNo, cardNo, JsonUtil.objectToJson(cardInfo)});
            if (cardInfo == null || cardInfo.isEmpty()) {
                resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                resTransfer.setResultMsg("卡信息不存在");
                return CommonResult.ok(resTransfer);
            }
            String mobileNo = StringUtil.filterNull(cardInfo.get("mobile_no"));
            String settleBankNo = StringUtil.filterNull(cardInfo.get("settle_bank_no"));
            String idCardNo = StringUtil.filterNull(cardInfo.get("id_card_no"));
            String accountName = StringUtil.filterNull(cardInfo.get("account_name"));
            String accountNo = StringUtil.filterNull(cardInfo.get("account_no"));
            String bankName = StringUtil.filterNull(cardInfo.get("bank_name"));
            String bankNo = StringUtil.filterNull(cardInfo.get("bank_no"));

            //再次判断当前明细编号是否是成功状态，如果是成功状态，则不允许新增统一出账订单记录了
            RepayPlanDetail detail = planDetailService.getDetailByPlanNo(planNo);
            log.info("代付还款明细编号[{}]对应明细信息[{}]", new Object[]{planNo, JsonUtil.objectToJson(detail)});
            if (detail == null || Constants.PLAN_DETAIL_STATUS_SUCCESS.equals(detail.getPlanStatus())) {
                resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                resTransfer.setResultMsg("明细不合法");
                return CommonResult.ok(resTransfer);
            }
            String batchNo = detail.getBatchNo();
            int planIndex = detail.getPlanIndex();

            //根据计划明细获取计划批次
            RepayPlan repayPlan = planService.getRepayPlanByBatchNo(batchNo);
            log.info("代付还款明细编号[{}]对应计划信息[{}]", new Object[]{planNo, JsonUtil.objectToJson(repayPlan)});
            if (repayPlan == null) {
                resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                resTransfer.setResultMsg("明细不合法");
                return CommonResult.ok(resTransfer);
            }
            String repayType = repayPlan.getRepayType();
            String repaySingleFee = "";
            String orderNo = "";
            //获取商户服务
            Map<String, Object> merFeeMap = merFeeService.getMerFeeByMerNoAndOemType(Constants.MER_TYPE_MERCHANT, merchantNo, oemType);
            if (merFeeMap == null || merFeeMap.isEmpty()) {
                resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                resTransfer.setResultMsg("商户费率有误");
                return CommonResult.ok(resTransfer);
            }
            if (Constants.REPAY_TYPE_QUICK.equals(repayType)) {
                repaySingleFee = String.valueOf(merFeeMap.get("quick_single_fee"));
            } else {
                repaySingleFee = String.valueOf(merFeeMap.get("perfect_single_fee"));
            }
            //先根据计划编号获取唯一的还款项目出账记录，如果存在则获取出账编号，如果不存在则新增
            WithdrawOrder withdrawOrder = withdrawOrderService.getWithdrawOrderByService(Constants.WITHDRAW_SERVICE_REPAY, planNo);
            if (null == withdrawOrder || !Constants.WITHDRAW_STATUS_SUCCESS.equals(withdrawOrder.getStatus())) {
                //新增统一出账表记录
                orderNo = WebUtil.nextUniqueSeqNo("t_withdraw_order", "TWOR", 25);
                withdrawOrder = new WithdrawOrder();
                withdrawOrder.setOrderNo(orderNo);
                withdrawOrder.setMerType(Constants.MER_TYPE_MERCHANT);
                withdrawOrder.setMerNo(merchantNo);
                withdrawOrder.setService(Constants.WITHDRAW_SERVICE_REPAY);
                withdrawOrder.setServiceOrderNo(planNo);
                withdrawOrder.setAcqCode(acqCode);
                withdrawOrder.setCardNo(cardNo);
                withdrawOrder.setAccountNo(accountNo);
                withdrawOrder.setAccountName(accountName);
                withdrawOrder.setAmount(amount);
                withdrawOrder.setFee(new BigDecimal(repaySingleFee));
                count = withdrawOrderService.saveWithdrawOrder(withdrawOrder);
                log.info("代付还款明细编号[{}]新增统一出账记录影响行数[{}]", new Object[]{planNo, count});
                if (count < 1) {
                    throw new RuntimeException("代付还款明细编号" + planNo + "代付错误信息-------->新增新增统一出账记录失败");
                }
                //计划明细操作次数加一次
                count = planDetailService.incrementDetailCount(planNo);
                log.info("代付还款明细编号[{}]操作次数加一影响的行数[{}]", new Object[]{planNo, count});
                if (count < 1) {
                    throw new RuntimeException("代付还款明细编号" + planNo + "代付错误信息-------->修改计划编号：" + planNo + "操作次数失败");
                }
            } else {
                orderNo = withdrawOrder.getOrderNo();
            }

            log.info("代付还款明细编号[{}]准备发起代付", new Object[]{planNo});

            TransferOrder payTransfer = new TransferOrder();
            payTransfer.setTradeSource(acqCode);
            payTransfer.setOrderType(Constants.WITHDRAW_SERVICE_REPAY);
            payTransfer.setSourceOrderNo(orderNo);
            payTransfer.setInAccNo(accountNo);
            payTransfer.setInAccName(accountName);
            payTransfer.setInSettleBankNo(settleBankNo);
            payTransfer.setInBankNo(StringUtils.isBlank(bankNo) ? settleBankNo : bankNo);
            payTransfer.setInBankName(bankName);
            payTransfer.setMobileNo(mobileNo);
            payTransfer.setIdentityType(Constants.ID_CARD);
            payTransfer.setIdentityNo(idCardNo);
            payTransfer.setAmount(new BigDecimal(amountStr));
            payTransfer.setMerType(Constants.MER_TYPE_MERCHANT);
            payTransfer.setMerNo(merchantNo);

            if (Constants.PAY_ACQ_CODE_CJ.equals(acqCode)) {
                //获取进件商户号
                ZqMerchant zqMerchant = zqMerchantService.getByMerAndAcq(merchantNo, Constants.PAY_ACQ_CODE_CJ);
                log.info("代付还款明细编号[{}]所属商户号[{}]对应进件商户信息[{}]", new Object[]{planNo, merchantNo, JsonUtil.objectToJson(zqMerchant)});
                if (null == zqMerchant) {
                    resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                    resTransfer.setResultMsg("商户未进件或进件失败");
                    return CommonResult.ok(resTransfer);
                }
                String zqMerchantNo = zqMerchant.getZqMerchantNo();
                String zqStatus = zqMerchant.getZqStatus();
                if (StringUtils.isEmpty(zqMerchantNo) || !Constants.ZQ_MER_STATUS_SUCC.equals(zqStatus)) {
                    resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                    resTransfer.setResultMsg("商户未进件或进件失败");
                    return CommonResult.ok(resTransfer);
                }
                payTransfer.setAcqMerNo(zqMerchantNo);

                //判断走D0还是T1模式，由上一条消费明细的创建时间为准
                RepayPlanDetail prevDetail = planDetailService.getPrevSuccessDetailByBatchNo(batchNo, planIndex);
                log.info("畅捷代付还款明细编号[{}]上一笔明细对象[{}]", new Object[]{planNo, JsonUtil.objectToJson(prevDetail)});
                if (prevDetail == null || !Constants.PLAN_DETAIL_TYPE_OUT.equals(prevDetail.getPlanType())) {
                    resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                    resTransfer.setResultMsg("上一笔明细状态不合法");
                    return CommonResult.ok(resTransfer);
                }
                //获取交易成功的订单号
                PayOrder succOrder = payOrderService.getPayOrderByService(Constants.PAY_ORDER_SERVICE_REPAY, prevDetail.getPlanNo());
                if (succOrder == null || !Constants.ORDER_TRANS_STATUS_SUCCESS.equals(succOrder.getTransStatus())) {
                    resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                    resTransfer.setResultMsg("上一笔消费明细对应订单状态不合法");
                    return CommonResult.ok(resTransfer);
                }
                Date succCreateTime = succOrder.getCreateTime();
                payTransfer.setBak2("400");
                if (DateUtil.daysBetween(new Date(), succCreateTime) != 0) {
                    payTransfer.setBak2("402");
                }
                //畅捷手续费自动从发起的金额里面扣除，所以此时发起的金额需要加上畅捷的代付成本
                Map<String, Object> routeChannel = WebUtil.getPayChannelInfo(acqCode);
                String acqSingleFee = StringUtil.filterNull(routeChannel.get("withdraw_single_fee"));
                payTransfer.setAmount(new BigDecimal(amountStr).add(new BigDecimal(acqSingleFee)));
            }
            log.info("代付还款明细编号[{}]代付参数", new Object[]{planNo, JsonUtil.objectToJson(payTransfer)});

            try {
                Transfer transfer = SpringUtil.getBean("transfer");
                resTransfer = transfer.pay(payTransfer);

            } catch (Exception e) {
                e.printStackTrace();
                log.info("代付还款明细编号[{}]代付异常", new Object[]{planNo, e});
                resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
                resTransfer.setResultMsg("代付异常");
                return CommonResult.ok(resTransfer);
            }

            if (StringUtils.isBlank(resTransfer.getSourceOrderNo())) {
                resTransfer.setSourceOrderNo(orderNo);
            }
            return CommonResult.ok(resTransfer);

        } catch (Exception e) {
            e.printStackTrace();
            log.info("代付还款明细编号[{}]代付异常", new Object[]{planNo, e});

            resTransfer.setStatus(Constants.TRANSFER_STATUS_FAIL);
            resTransfer.setResultMsg("代付异常");
            return CommonResult.ok(resTransfer);
        }
    }
}